package com.xinzhidi.web.house.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinzhidi.common.constant.AgreementConstants;
import com.xinzhidi.common.core.domain.entity.SysDictData;
import com.xinzhidi.common.core.domain.entity.SysUser;
import com.xinzhidi.common.core.domain.model.LoginUser;
import com.xinzhidi.common.core.page.TableDataInfo;
import com.xinzhidi.common.core.text.Convert;
import com.xinzhidi.common.exception.ServiceException;
import com.xinzhidi.common.utils.DateUtils;
import com.xinzhidi.common.utils.SecurityUtils;
import com.xinzhidi.common.utils.StringUtils;
import com.xinzhidi.common.utils.bean.BeanUtils;
import com.xinzhidi.common.utils.bean.BeanValidators;
import com.xinzhidi.common.utils.poi.ExcelUtil;
import com.xinzhidi.system.mapper.SysDictDataMapper;
import com.xinzhidi.system.service.ISysDictTypeService;
import com.xinzhidi.system.service.ISysUserService;
import com.xinzhidi.web.build.domain.BuildUnit;
import com.xinzhidi.web.build.domain.CBuild;
import com.xinzhidi.web.build.service.IBuildUnitService;
import com.xinzhidi.web.build.service.ICBuildService;
import com.xinzhidi.web.custommodel.domain.CustomModel;
import com.xinzhidi.web.custommodel.service.CustomModelService;
import com.xinzhidi.web.dtuusr.domain.DtuUsr;
import com.xinzhidi.web.dtuusr.service.DtuUsrService;
import com.xinzhidi.web.equipment.domain.Equipment;
import com.xinzhidi.web.equipment.service.EquipmentService;
import com.xinzhidi.web.house.domain.Household;
import com.xinzhidi.web.house.domain.dto.HouseholdAddDto;
import com.xinzhidi.web.house.domain.dto.HouseholdListDto;
import com.xinzhidi.web.house.domain.dto.HouseholdUpdDto;
import com.xinzhidi.web.house.domain.vo.HouseholdExcelVo;
import com.xinzhidi.web.house.domain.vo.HouseholdImportVo;
import com.xinzhidi.web.house.domain.vo.HouseholdInfoVo;
import com.xinzhidi.web.house.domain.vo.HouseholdListVo;
import com.xinzhidi.web.house.mapper.HouseholdMapper;
import com.xinzhidi.web.house.service.IHouseholdService;
import com.xinzhidi.web.netty.utils.SecurityAdminUtils;
import com.xinzhidi.web.plot.domain.entity.CPlot;
import com.xinzhidi.web.plot.domain.vo.SelectVo;
import com.xinzhidi.web.plot.service.impl.CPlotServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Validator;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 住户Service业务层处理
 *
 * @author cx
 * @date 2023-05-23
 */
@Service
public class HouseholdServiceImpl extends ServiceImpl<HouseholdMapper, Household> implements IHouseholdService {

    @Autowired
    private CustomModelService customModelService;

    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    protected Validator validator;
    @Autowired
    private CPlotServiceImpl plotService;
    @Autowired
    private ICBuildService buildService;
    @Autowired
    private IBuildUnitService unitService;

    @Autowired
    private ISysDictTypeService dictTypeService;

    @Autowired
    private DtuUsrService dtuUsrService;

    @Autowired
    private EquipmentService equipmentService;

    @Autowired
    private SysDictDataMapper sysDictDataMapper;


    /**
     * 查询住户
     *
     * @param id 住户主键
     * @return 住户
     */
    @Override
    public HouseholdInfoVo selectHouseholdById(Long id) {
        HouseholdInfoVo infoVo = this.baseMapper.selectHouseholdInfo(id);
        if (infoVo != null) {
            List<CustomModel> modelList = customModelService.getModelByIds(infoVo.getModelIds());
            infoVo.setCustomModels(modelList);
        }
        return infoVo;
    }

    /**
     * 查询住户列表
     *
     * @param dto 查询住户dto
     * @return 住户
     */
    @Override
    public TableDataInfo<HouseholdListVo> selectHouseholdList(HouseholdListDto dto) {

        List<HouseholdListVo> selectHouseholdListVo;
        List<Long> userPlotIds = SecurityAdminUtils.getUserPlotIds();

        selectHouseholdListVo = baseMapper.selectHouseholdListVo(dto, userPlotIds);
        if (CollectionUtils.isNotEmpty(selectHouseholdListVo)) {
            Map<Long, String> useridMapName = sysUserService.list(new LambdaQueryWrapper<>(SysUser.class).in(SysUser::getUserId, selectHouseholdListVo.stream().map(HouseholdListVo::getCreateBy).collect(Collectors.toList()))).stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getUserName));
            for (HouseholdListVo vo : selectHouseholdListVo) {
                vo.setCreateName(useridMapName.get(Convert.toLong(vo.getCreateBy())));
                String modelIds = vo.getModelIds();
                if (StringUtils.isNotBlank(modelIds)) {
                    List<CustomModel> modelList = customModelService.getModelByIds(modelIds);
                    vo.setCustomModels(modelList);
                }
            }
        }
        return TableDataInfo.getDataTable(selectHouseholdListVo);
    }

    /**
     * 查询住户列表
     *
     * @param dto 查询住户dto
     * @return 住户
     */
    @Override
    public TableDataInfo<SelectVo> listHouseholdSelect(HouseholdListDto dto) {

        List<HouseholdListVo> selectHouseholdListVo;
        List<Long> userPlotIds = SecurityAdminUtils.getUserPlotIds();

        selectHouseholdListVo = baseMapper.selectHouseholdListVo(dto, userPlotIds);

        return TableDataInfo.getDataTable(selectHouseholdListVo, (domain -> {
            SelectVo vo = new SelectVo();
            vo.setValue(domain.getId().toString());
            vo.setLabel(domain.getHouseNumber());
            return vo;
        }));
    }

    /**
     * 新增住户
     *
     * @param dto 新增住户dto
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertHousehold(HouseholdAddDto dto) {
        if (CollectionUtils.isNotEmpty(list(new LambdaQueryWrapper<>(Household.class).eq(Household::getHouseNumber, dto.getHouseNumber()).eq(Household::getUnit, dto.getUnit())))) {
            throw new ServiceException(dto.getHouseNumber() + "已存在！");
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();

        Household household = new Household();
        BeanUtils.copyProperties(dto, household);
        household.setCreateBy(loginUser.getUserId().toString());
        household.setCreateTime(DateUtils.getNowDate());
        int rows = this.baseMapper.insert(household);
        this.baseMapper.updateTotalHouseNum(dto.getBuildId(), dto.getUnit());
        return rows;
    }

    /**
     * 修改住户
     *
     * @param dto 修改住户dto
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateHousehold(HouseholdUpdDto dto) {
        if (CollectionUtils.isNotEmpty(list(new LambdaQueryWrapper<>(Household.class).eq(Household::getHouseNumber, dto.getHouseNumber()).eq(Household::getUnit, dto.getUnit()).ne(Household::getId, dto.getId())))) {
            throw new ServiceException(dto.getHouseNumber() + "已存在！");
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();

        Household household = new Household();
        BeanUtils.copyProperties(dto, household);
        household.setUpdateBy(loginUser.getUserId().toString());
        household.setUpdateTime(DateUtils.getNowDate());
        this.baseMapper.deleteCBuildById(household.getId());
        this.baseMapper.updateTotalHouseNum(dto.getBuildId(), dto.getUnit());
        return this.baseMapper.updateById(household);
    }

    /**
     * 批量删除住户
     *
     * @param ids 需要删除的住户主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteHouseholdByIds(Long[] ids) {
        updateDataByDeleteIds(Arrays.asList(ids));
        List<Household> households = this.baseMapper.selectBatchIds(Arrays.asList(ids));
        this.baseMapper.deleteCBuildByIds(ids);
        int i = this.baseMapper.deleteBatchIds(Arrays.asList(ids));
        households.stream().forEach(item -> {
            this.baseMapper.updateTotalHouseNum(item.getBuildId(), item.getUnit());
        });

        return i;
    }

    /**
     * 删除住户信息
     *
     * @param id 住户主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteHouseholdById(Long id) {
        Household household = this.baseMapper.selectById(id);
        this.baseMapper.deleteCBuildById(id);
        this.baseMapper.updateTotalHouseNum(household.getBuildId(), household.getUnit());
        return 1;
    }

    /**
     * 导入用户数据
     *
     * @param importVoList    用户数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @return 结果
     */
    @Override
    public String importBuild(List<HouseholdImportVo> importVoList, Boolean isUpdateSupport) {
        //基础校验数据
        if (StringUtils.isNull(importVoList) || importVoList.size() == 0) {
            throw new ServiceException("导入用户数据不能为空！");
        }
        Long userId = SecurityUtils.getLoginUser().getUserId();
        List<Long> plotids = SecurityAdminUtils.getUserPlotIds();
        if (CollectionUtils.isEmpty(plotids)) {
            throw new ServiceException("当前用户无小区权限，不能导入");
        }
        SysDictData sysDictData;
        DtuUsr dtuUsr;
        LambdaQueryWrapper<DtuUsr> dtuWrapper;
        String protocolType;
        //协议协议类型字典数据
        List<SysDictData> protocolTypeDictDataList = sysDictDataMapper.selectDictDataByType("protocol_type");
        //开始导入
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        Map<String, CPlot> nameMapEntity = plotService.listByIds(plotids).stream().collect(Collectors.toMap(CPlot::getParkName, Function.identity(), (key1, key2) -> key1));

        Map<Long, Map<String, CBuild>> plotIdMapBuildIdMapBuild = buildService.list(new LambdaQueryWrapper<CBuild>(CBuild.class).in(CBuild::getPlotId, plotids))
                .stream().collect(Collectors.groupingBy(build -> build.getPlotId()))
                .entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().stream().collect(Collectors.toMap(CBuild::getBuildName, CBuild -> CBuild, (u1, u2) -> u2))));

        Map<Long, Map<String, BuildUnit>> builIdMapunit = unitService.list(new LambdaQueryWrapper<BuildUnit>(BuildUnit.class).in(BuildUnit::getLotId, plotids))
                .stream().collect(Collectors.groupingBy(build -> build.getBuildId()))
                .entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().stream().collect(Collectors.toMap(BuildUnit::getUnitName, BuildUnit -> BuildUnit))));
        Map<Long, Map<String, Household>> uniIdMapHousehold = list(new LambdaQueryWrapper<Household>(Household.class).in(Household::getPlotId, plotids))
                .stream().collect(Collectors.groupingBy(household -> household.getUnit()))
                .entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().stream().collect(Collectors.toMap(Household::getHouseNumber, Household -> Household))));

        for (int i = 0; i < importVoList.size(); i++) {
            HouseholdImportVo vo = importVoList.get(i);
            Integer num = i + 1;
            CPlot cPlot = nameMapEntity.get(vo.getPlotName());
            if (cPlot == null) {
                throw new ServiceException("当前用户无【" + vo.getPlotName() + "】小区权限，不能导入");
            } else {
                vo.setPlotId(cPlot.getId());
            }
            BeanValidators.validateWithException(validator, vo);
            //楼栋
            Map<String, CBuild> stringCBuildMap = plotIdMapBuildIdMapBuild.get(cPlot.getId());
            if (stringCBuildMap == null || stringCBuildMap.get(vo.getBuildName()) == null) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、第" + num + "行【" + vo.getBuildName() + "】楼栋不存在，不能导入");
                importVoList.remove(i);
                continue;
            }
            CBuild cBuild = stringCBuildMap.get(vo.getBuildName());
            vo.setBuildId(cBuild.getId());

            //单元
            Map<String, BuildUnit> stringBuildUnitMap = builIdMapunit.get(cBuild.getId());
            if (stringBuildUnitMap == null || stringBuildUnitMap.get(vo.getUnitName()) == null) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、第" + num + "行【" + vo.getUnitName() + "】单元不存在，不能导入");
                importVoList.remove(i);
                continue;
            }
            BuildUnit buildUnit = stringBuildUnitMap.get(vo.getUnitName());
            vo.setUnit(buildUnit.getId());

            Integer times = StringUtils.containFrequency(vo.getHouseNumber(), '-');
            if (times != 0) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、第" + num + "行【" + vo.getHouseNumber() + "】格式错误，正确格式为：1001");
                importVoList.remove(i);
                continue;
            }

            if (vo.getHouseNumber().length() != 4) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、第" + num + "行【" + vo.getHouseNumber() + "】格式错误，位数为4位，如：：1001");
                importVoList.remove(i);
                continue;
            }

            //判断是否有设备的导入
            String protocolTypeName = vo.getProtocolTypeName();
            if (StringUtils.isNotBlank(protocolTypeName)) {
                String address = vo.getAddress();
                if (StringUtils.isBlank(address)) {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、第" + num + "行【" + vo.getHouseNumber() + "】设备地址不能为空");
                    importVoList.remove(i);
                }
                String equipmentCode = vo.getEquipmentCode();
                if (StringUtils.isBlank(equipmentCode)) {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、第" + num + "行【" + vo.getHouseNumber() + "】设备编号不能为空");
                    importVoList.remove(i);
                }
                String equipmentTypeName = vo.getEquipmentTypeName();
                if (StringUtils.isBlank(equipmentTypeName)) {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、第" + num + "行【" + vo.getHouseNumber() + "】设备类型不能为空");
                    importVoList.remove(i);
                }
                //是否为室温采集器协议  true:是  false:否
                boolean flag = vo.getProtocolTypeName().equals(AgreementConstants.AgreementTypeName.GREENHOUSE_COLLECTOR);
                if (!flag) {
                    dtuWrapper = new LambdaQueryWrapper<>();
                    dtuWrapper.eq(DtuUsr::getName, vo.getDtuName());
                    dtuUsr = dtuUsrService.getOne(dtuWrapper);
                    if (dtuUsr == null) {
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、第" + num + "行dtu名称不存在");
                        importVoList.remove(i);
                    } else {
                        vo.setDtuId(dtuUsr.getId());
                    }
                }

            }

        }

        //需要更新供热面积、供热用户的小区id集合
        Set<Long> updatePlotIds = new HashSet<>();

        //需要更新供热面积、供热用户的楼栋id集合
        Set<Long> updateBuildIds = new HashSet<>();

        //需要更新供热面积、供热用户的单元id集合
        Set<Long> updateUnitIds = new HashSet<>();

        Equipment equipment;
        List<Equipment> equipmentList = Lists.newArrayList();
        for (int i = 0; i < importVoList.size(); i++) {

            HouseholdImportVo vo = importVoList.get(i);
            Integer num = i + 1;
            try {
                Household entity = null;
                // 验证是否存在这个用户
                CPlot cPlot = nameMapEntity.get(vo.getPlotName());
                //楼栋
                Map<String, CBuild> stringCBuildMap = plotIdMapBuildIdMapBuild.get(cPlot.getId());
                CBuild cBuild = stringCBuildMap.get(vo.getBuildName());

                //单元
                Map<String, BuildUnit> stringBuildUnitMap = builIdMapunit.get(cBuild.getId());
                BuildUnit buildUnit = stringBuildUnitMap.get(vo.getUnitName());
                Map<String, Household> stringHouseholdMap = uniIdMapHousehold.get(buildUnit.getId());

                Long floor = Long.valueOf(vo.getHouseNumber().substring(0, vo.getHouseNumber().length() - 2));
                vo.setHouseNumber(StringUtils.getInteger(vo.getBuildName()) + "-" + StringUtils.getInteger(vo.getUnitName()) + "-" + StringUtils.getInteger(vo.getHouseNumber()));
                if (stringHouseholdMap != null && stringHouseholdMap.get(vo.getHouseNumber()) != null) {
                    entity = stringHouseholdMap.get(vo.getHouseNumber());
                }
                if (StringUtils.isNull(entity)) {
                    entity = new Household();
                    BeanUtils.copyProperties(vo, entity);
                    entity.setUnit(buildUnit.getId());
                    entity.setCreateBy(userId.toString());
                    entity.setFloor(floor);
                    this.save(entity);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、第" + num + "行门牌号 " + vo.getHouseNumber() + " 导入成功");
                    updatePlotIds.add(cPlot.getId());
                    updateBuildIds.add(cBuild.getId());
                    updateUnitIds.add(buildUnit.getId());
                } else {
                    BeanValidators.validateWithException(validator, vo);
                    vo.setId(entity.getId());
                    BeanUtils.copyProperties(vo, entity);
                    entity.setFloor(floor);
                    entity.setUpdateBy(userId.toString());
                    this.updateById(entity);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、第" + num + "行门牌号 " + vo.getHouseNumber() + " 更新成功");
                    updatePlotIds.add(cPlot.getId());
                    updateBuildIds.add(cBuild.getId());
                    updateUnitIds.add(buildUnit.getId());
                }


                equipment = equipmentService.getOne(Wrappers.<Equipment>lambdaQuery().eq(Equipment::getAddress, vo.getAddress()));
                if (equipment == null) {
                    equipment = new Equipment();
                    equipment.setDtuId(vo.getDtuId());
                    equipment.setEquipmentLevel(AgreementConstants.DataType.HOUSEHOLD);
                    equipment.setEquipmentType(equipmentService.getEquipmentType(vo.getProtocolTypeName()));
                    equipment.setLotId(cPlot.getId());
                    equipment.setBuildId(cBuild.getId());
                    equipment.setUnitId(buildUnit.getId());
                    equipment.setHouseholdId(entity.getId());
                    if (StringUtils.isNotBlank(vo.getEquipmentName())) {
                        equipment.setEquipmentName(vo.getEquipmentName());
                    }
                    equipment.setEquipmentCode(vo.getEquipmentCode());
                    equipment.setEquipmentType(equipmentService.getEquipmentType(vo.getEquipmentTypeName()));
                    equipment.setAddress(vo.getAddress());
                    equipment.setAutoRead("1");
                    equipment.setCreateBy(userId.toString());
                    equipmentList.add(equipment);
                }

                if (vo.getBuildId() != null && vo.getUnit() != null) {
                    this.baseMapper.updateTotalHouseNum(vo.getBuildId(), vo.getUnit());
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、第" + num + "行门牌号 " + vo.getHouseNumber() + " 导入失败";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (!equipmentList.isEmpty()) {
            equipmentService.saveOrUpdateBatch(equipmentList);
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }

        if (updatePlotIds.size() > 0) {
            this.updateData(AgreementConstants.DataType.PLOT, new ArrayList<>(updatePlotIds));
        }
        if (updateBuildIds.size() > 0) {
            this.updateData(AgreementConstants.DataType.BUILD, new ArrayList<>(updateBuildIds));
        }
        if (updateUnitIds.size() > 0) {
            this.updateData(AgreementConstants.DataType.BUILD_UNIT, new ArrayList<>(updateUnitIds));
        }
        return successMsg.toString();
    }

    @Override
    public List<Long> getHouseholdIdsByModelIds(List<Integer> modelIds, String protocolType) {
        List<Long> ids = Lists.newArrayList();
        if (CollectionUtils.isEmpty(modelIds)) {
            return ids;
        }
        List<Household> households = this.baseMapper.getHouseholdIdsByModelIds(modelIds, protocolType);
        if (CollectionUtils.isNotEmpty(households)) {
            ids = households.stream().map(Household::getId).collect(Collectors.toList());
        }
        return ids;
    }

    @Override
    public void updateData(String DataType, List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        Integer heatUser;
        BigDecimal heatArea;

        List<Household> list;
        LambdaQueryWrapper<Household> wrapper;
        CPlot plot;
        CBuild build;
        BuildUnit unit;
        List<CPlot> plotList = Lists.newArrayList();
        List<CBuild> buildList = Lists.newArrayList();
        List<BuildUnit> unitList = Lists.newArrayList();
        if ("0".equals(DataType)) {
            //小区
            for (Long id : ids) {
                plot = plotService.getById(id);
                wrapper = Wrappers.lambdaQuery();
                wrapper.eq(Household::getPlotId, id);
                list = this.baseMapper.selectList(wrapper);
                if (CollectionUtils.isEmpty(list)) {
                    break;
                }
                heatUser = list.size();
                heatArea = list.stream().filter(item -> item.getHeatArea() != null && item.getHeatArea().compareTo(BigDecimal.ZERO) > 0)
                        .map(Household::getHeatArea).reduce(BigDecimal.ZERO, BigDecimal::add);

                plot.setHeatArea(heatArea);
                plot.setHeatUser(heatUser);
                plotList.add(plot);
            }
        } else if ("1".equals(DataType)) {
            //楼栋
            for (Long id : ids) {
                build = buildService.getById(id);
                wrapper = Wrappers.lambdaQuery();
                wrapper.eq(Household::getBuildId, id);
                list = this.baseMapper.selectList(wrapper);
                if (CollectionUtils.isEmpty(list)) {
                    break;
                }
                heatUser = list.size();
                heatArea = list.stream().filter(item -> item.getHeatArea() != null && item.getHeatArea().compareTo(BigDecimal.ZERO) > 0)
                        .map(Household::getHeatArea).reduce(BigDecimal.ZERO, BigDecimal::add);

                build.setHeatArea(heatArea);
                build.setHeatingHouseNumber(heatUser);
                buildList.add(build);
            }
        } else if ("2".equals(DataType)) {
            //单元
            for (Long id : ids) {
                unit = unitService.getById(id);
                wrapper = Wrappers.lambdaQuery();
                wrapper.eq(Household::getUnit, id);
                list = this.baseMapper.selectList(wrapper);
                if (CollectionUtils.isEmpty(list)) {
                    break;
                }
                heatUser = list.size();
                heatArea = list.stream().filter(item -> item.getHeatArea() != null && item.getHeatArea().compareTo(BigDecimal.ZERO) > 0)
                        .map(Household::getHeatArea).reduce(BigDecimal.ZERO, BigDecimal::add);

                unit.setHeatArea(heatArea);
                unit.setHeatNumber(heatUser);
                unitList.add(unit);
            }
        }

        if (plotList.size() > 0) {
            plotService.updateBatchById(plotList);
        } else if (buildList.size() > 0) {
            buildService.updateBatchById(buildList);
        } else if (unitList.size() > 0) {
            unitService.updateBatchById(unitList);
        }

    }

    @Override
    public void updateDataByDeleteIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        BigDecimal heatArea;

        List<Household> list;
        LambdaQueryWrapper<Household> wrapper = Wrappers.lambdaQuery();
        wrapper.in(Household::getId, ids);
        CPlot plot;
        CBuild build;
        BuildUnit unit;
        List<CPlot> plotList = Lists.newArrayList();
        List<CBuild> buildList = Lists.newArrayList();
        List<BuildUnit> unitList = Lists.newArrayList();
        list = this.baseMapper.selectList(wrapper);

        Map<Long, List<Household>> plotMap = list.stream().collect(Collectors.groupingBy(Household::getPlotId));
        Map<Long, List<Household>> buildMap = list.stream().collect(Collectors.groupingBy(Household::getBuildId));
        Map<Long, List<Household>> unitMap = list.stream().collect(Collectors.groupingBy(Household::getUnit));

        for (Map.Entry<Long, List<Household>> entry : plotMap.entrySet()) {
            Long key = entry.getKey();
            plot = plotService.getById(key);
            List<Household> households = entry.getValue();
            heatArea = households.stream().filter(item -> item.getHeatArea() != null && item.getHeatArea().compareTo(BigDecimal.ZERO) > 0)
                    .map(Household::getHeatArea).reduce(BigDecimal.ZERO, BigDecimal::add);
            plot.setHeatUser(plot.getHeatUser() - households.size());
            if (plot.getHeatArea() != null) {
                plot.setHeatArea(plot.getHeatArea().subtract(heatArea));
            }
            plotList.add(plot);
        }

        for (Map.Entry<Long, List<Household>> entry : buildMap.entrySet()) {
            Long key = entry.getKey();
            build = buildService.getById(key);
            List<Household> households = entry.getValue();
            heatArea = households.stream().filter(item -> item.getHeatArea() != null && item.getHeatArea().compareTo(BigDecimal.ZERO) > 0)
                    .map(Household::getHeatArea).reduce(BigDecimal.ZERO, BigDecimal::add);
            if(build.getHeatingHouseNumber() != null){
                build.setHeatingHouseNumber(build.getHeatingHouseNumber() - households.size());
            }
            if (build.getHeatArea() != null) {
                build.setHeatArea(build.getHeatArea().subtract(heatArea));
            }
            buildList.add(build);
        }

        for (Map.Entry<Long, List<Household>> entry : unitMap.entrySet()) {
            Long key = entry.getKey();
            unit = unitService.getById(key);
            List<Household> households = entry.getValue();
            heatArea = households.stream().filter(item -> item.getHeatArea() != null && item.getHeatArea().compareTo(BigDecimal.ZERO) > 0)
                    .map(Household::getHeatArea).reduce(BigDecimal.ZERO, BigDecimal::add);
            unit.setHeatNumber(unit.getHeatNumber() - households.size());
            if (unit.getHeatArea() != null) {
                unit.setHeatArea(unit.getHeatArea().subtract(heatArea));
            }
            unitList.add(unit);
        }
        plotService.updateBatchById(plotList);
        buildService.updateBatchById(buildList);
        unitService.updateBatchById(unitList);

    }

    @Override
    public void setBox() {
        //设置楼栋热计量方式
//        setBuildHeatMeter();
        //设置协议类型
        setProtocolType();
        //设置小区热计量方式
//        setPlotUnitHeatMeter();
        //设置单元热计量方式
//        setBuildUnitHeatMeter();
        //设置是否供暖
//        setHeatingOrNot();
        //设置dtu名称
        setDtuName();
        //设置主动超标
//        setAutoRead();

    }

    public void setAutoRead() {
        List<String> list = Arrays.asList("是", "否");
        Field file;
        try {
            file = HouseholdExcelVo.class.getDeclaredField("autoRead");
            ExcelUtil.setCombo(file, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void setDtuName() {
        List<DtuUsr> data = dtuUsrService.list();
        if (CollectionUtils.isEmpty(data)) {
            return;
        }
        List<String> list = data.stream().map(DtuUsr::getName).collect(Collectors.toList());
        Field file;
        try {
            file = HouseholdExcelVo.class.getDeclaredField("dtuName");
            ExcelUtil.setCombo(file, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void setProtocolType() {
        List<SysDictData> data = dictTypeService.selectDictDataByType("protocol_type");
        if (CollectionUtils.isEmpty(data)) {
            return;
        }
        List<String> list = data.stream().map(SysDictData::getDictLabel).collect(Collectors.toList());
        Field file;
        try {
            file = HouseholdExcelVo.class.getDeclaredField("protocolName");
            ExcelUtil.setCombo(file, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void setBuildHeatMeter() {
        List<SysDictData> data = dictTypeService.selectDictDataByType("sys_heat_meter");
        if (CollectionUtils.isEmpty(data)) {
            return;
        }
        List<String> list = data.stream().map(SysDictData::getDictLabel).collect(Collectors.toList());
        Field file;
        try {
            file = HouseholdExcelVo.class.getDeclaredField("buildHeatMeter");
            ExcelUtil.setCombo(file, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void setPlotUnitHeatMeter() {
        List<SysDictData> data = dictTypeService.selectDictDataByType("sys_heat_meter");
        if (CollectionUtils.isEmpty(data)) {
            return;
        }
        List<String> list = data.stream().map(SysDictData::getDictLabel).collect(Collectors.toList());
        Field file;
        try {
            file = HouseholdExcelVo.class.getDeclaredField("plotHeatMeter");
            ExcelUtil.setCombo(file, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void setBuildUnitHeatMeter() {
        List<SysDictData> data = dictTypeService.selectDictDataByType("sys_heat_meter");
        if (CollectionUtils.isEmpty(data)) {
            return;
        }
        List<String> list = data.stream().map(SysDictData::getDictLabel).collect(Collectors.toList());
        Field file;
        try {
            file = HouseholdExcelVo.class.getDeclaredField("unitHeatMeter");
            ExcelUtil.setCombo(file, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void setHeatingOrNot() {
        List<String> list = Arrays.asList("是", "否");
        Field file;
        try {
            file = HouseholdExcelVo.class.getDeclaredField("heatingOrNot");
            ExcelUtil.setCombo(file, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}